/*
 * Copyright 2014 ptma@163.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.joy.db.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.joy.db.model.util.JavaTypeResolver;
import org.joy.util.StringUtil;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class Column implements Serializable {

    private static final long serialVersionUID = 6987289314682844881L;

    private String            columnName;

    private boolean           primaryKey;

    private boolean           foreignKey;

    private int               size;

    private int               decimalDigits;

    private boolean           nullable;

    private boolean           unique;

    private boolean           indexed;

    private boolean           autoincrement;

    private String            defaultValue;

    private String            remarks;

    protected int             jdbcType;
    protected String          jdbcTypeName;

    private String            javaProperty;
    private String            javaType;
    private String            fullJavaType;
    private String            editor;
    private boolean           display          = true;
    private boolean           searchable;
    private String            dict = "";
    private String            ui;
    private int			  x;
    private int			  y;
    private int			  lableX;
    private int			  lableY;
    private int			  width;
    private int			  lableWidth;
    private int			  height;
    private int			  page;
    private boolean			  fullRow	= false;
    private boolean			  require	= false;
    private boolean			  editable	= true;
    private String			  groupNo = "0";
    public final static int fullWith = 855;

    public Column(String columnName){
        this.columnName = columnName;
        this.javaProperty = StringUtil.getCamelCaseString(columnName, false);
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public int getDecimalDigits() {
        return decimalDigits;
    }

    public void setDecimalDigits(int decimalDigits) {
        this.decimalDigits = decimalDigits;
    }

    public boolean isNullable() {
        return nullable;
    }

    public void setNullable(boolean nullable) {
        this.nullable = nullable;
    }

    public String getDefaultValue() {
        return defaultValue == null ? "" : defaultValue;
    }

    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }

    public String getRemarks() {
        return remarks == null ? "" : remarks.trim();
    }

    public boolean isHasRemarks() {
        return StringUtil.isNotEmpty(remarks);
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }

    public String getRemarksUnicode() {
        return StringUtil.toUnicodeString(getRemarks());
    }

    public String getJavaType() {
        return javaType;
    }

    public void setJavaType(String javaType) {
        this.javaType = javaType;
    }

    public String getJavaProperty() {
        return javaProperty;
    }

    public int getJdbcType() {
        return jdbcType;
    }

    public void setJdbcType(int jdbcType) {
        this.jdbcType = jdbcType;
    }

    public String getJdbcTypeName() {
        return jdbcTypeName;
    }

    public void setJdbcTypeName(String jdbcTypeName) {
        this.jdbcTypeName = jdbcTypeName;
    }

    public boolean isString() {
        return JavaTypeResolver.isString(javaType);
    }

    public boolean isFloatNumber() {
        return JavaTypeResolver.isFloat(javaType) || JavaTypeResolver.isDouble(javaType)
               || JavaTypeResolver.isBigDecimal(javaType) || JavaTypeResolver.isBigInteger(javaType);
    }

    public boolean isIntegerNumber() {
        return JavaTypeResolver.isByte(javaType) || JavaTypeResolver.isShort(javaType)
               || JavaTypeResolver.isInteger(javaType) || JavaTypeResolver.isLong(javaType);
    }

    public boolean isBigDecimal() {
        return JavaTypeResolver.isBigDecimal(javaType);
    }

    public boolean isBoolean() {
        return JavaTypeResolver.isBoolean(javaType);
    }

    public boolean isDate() {
        return JavaTypeResolver.isDate(javaType);
    }

    public boolean isBLOB() {
        String typeName = getJdbcTypeName();
        boolean isBlob = "BINARY".equals(typeName);
        isBlob = isBlob || "BLOB".equals(typeName);
        isBlob = isBlob || "CLOB".equals(typeName);
        isBlob = isBlob || "LONGVARBINARY".equals(typeName);
        isBlob = isBlob || "LONGVARCHAR".equals(typeName);
        isBlob = isBlob || "VARBINARY".equals(typeName);
        return isBlob;
    }

    public boolean isPrimitiveType(){
        //int, double, float, long, short, boolean, byte, char
        return JavaTypeResolver.isInteger(javaType)
            || JavaTypeResolver.isDouble(javaType)
            || JavaTypeResolver.isFloat(javaType)
            || JavaTypeResolver.isLong(javaType)
            || JavaTypeResolver.isShort(javaType)
            || JavaTypeResolver.isBoolean(javaType)
            || JavaTypeResolver.isByte(javaType);
    }

    public String getJavaPrimitiveType() {
        if (JavaTypeResolver.isInteger(javaType)){
            return "int";
        } else if (JavaTypeResolver.isDouble(javaType)){
            return "double";
        } else if (JavaTypeResolver.isFloat(javaType)){
            return "float";
        } else if (JavaTypeResolver.isLong(javaType)){
            return "long";
        } else if (JavaTypeResolver.isShort(javaType)){
            return "short";
        } else if (JavaTypeResolver.isBoolean(javaType)){
            return "boolean";
        } else if (JavaTypeResolver.isByte(javaType)){
            return "byte";
        } else {
            return javaType;
        }
    }

    public boolean isUnique() {
        return unique;
    }

    public void setUnique(boolean unique) {
        this.unique = unique;
    }

    public boolean isPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(boolean primaryKey) {
        this.primaryKey = primaryKey;
    }

    public boolean isForeignKey() {
        return foreignKey;
    }

    public void setForeignKey(boolean foreignKey) {
        this.foreignKey = foreignKey;
    }

    public void setJavaProperty(String javaProperty) {
        this.javaProperty = javaProperty;
    }

    public String getGetterMethodName() {
        StringBuilder sb = new StringBuilder();

        sb.append(javaProperty);
        if (Character.isLowerCase(sb.charAt(0)) && ((sb.length() == 1) || Character.isLowerCase(sb.charAt(1)))) {
            sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
        }

        if (JavaTypeResolver.isBoolean(javaType)) {
            sb.insert(0, "is");
        } else {
            sb.insert(0, "get");
        }

        return sb.toString();
    }

    public String getSetterMethodName() {
        StringBuilder sb = new StringBuilder();

        sb.append(javaProperty);
        if (Character.isLowerCase(sb.charAt(0)) && ((sb.length() == 1) || Character.isLowerCase(sb.charAt(1)))) {
            sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
        }

        sb.insert(0, "set");

        return sb.toString();
    }

    public String getFullJavaType() {
        return fullJavaType;
    }

    public void setFullJavaType(String fullJavaType) {
        this.fullJavaType = fullJavaType;
    }

    public String getEditor() {
        return editor;
    }

    public void setEditor(String editor) {
        this.editor = editor;
    }

    public boolean isAutoincrement() {
        return autoincrement;
    }

    public void setAutoincrement(boolean autoincrement) {
        this.autoincrement = autoincrement;
    }

    public boolean isIndexed() {
        return indexed;
    }

    public void setIndexed(boolean indexed) {
        this.indexed = indexed;
    }

    public boolean isDisplay() {
        return display;
    }

    public void setDisplay(boolean display) {
        this.display = display;
    }

    public boolean isSearchable() {
        return searchable;
    }

    public void setSearchable(boolean searchable) {
        this.searchable = searchable;
    }

    public String getDict() {
        return dict;
    }

    public boolean hasDict() {
        return StringUtil.isNotEmpty(dict);
    }
    public void setDict(String dict) {
        this.dict = dict;
    }

	public String getUi() {
		return ui;
	}

	public void setUi(String ui) {
		this.ui = ui;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getLableX() {
		return lableX;
	}

	public void setLableX(int lableX) {
		this.lableX = lableX;
	}

	public int getLableY() {
		return lableY;
	}

	public void setLableY(int lableY) {
		this.lableY = lableY;
	}

	public int getWidth() {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getLableWidth() {
		return lableWidth;
	}

	public void setLableWidth(int lableWidth) {
		if(this.ui.equals("CheckBox")){
			this.lableWidth = 15;
		}else if(this.ui.equals("RadioButton")){
			/*
			List<Map> list = getRadioButtonDate();
			if(list.size()==0){
				this.lableWidth = lableWidth;
			}else{
//				this.lableWidth = lableWidth;
				for(Map radio:list){
				String radioLable = (String)radio.get("label");
				this.lableWidth += 15*(radioLable.length()+2);
				}
			}
			*/
			this.lableWidth = lableWidth;
		}else{
			this.lableWidth = lableWidth;
		}
	}

	public int getHeight() {
		//TextAreas 默认为90
		if (this.ui.equals("TextAreas"))
			return 90;
		if (this.ui.equals("RadioButton")){
			List<Map> list = getRadioButtonDate();
			int radioHeight = 20;
			int radiowidth = remarks.length() * 12;
			for(Map radio:list){
				String radioLable = (String)radio.get("label");
				radiowidth += 15*(radioLable.length()+2);
			}
			if(radiowidth>fullWith){
				radioHeight = (int)(Math.ceil((double)radiowidth/(double)fullWith)*20);
			}
			return radioHeight;
		}
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public boolean isFullRow() {
		//TextAreas 默认为整行
		if (this.ui.equals("TextAreas")||this.ui.equals("RadioButton"))
//		if (this.ui.equals("TextAreas"))
			return true;
		return fullRow;
	}

	public void setFullRow(boolean fullRow) {
		this.fullRow = fullRow;
	}
	
	public void clearXY(){
		this.x = 0;
		this.y = 0;
		this.lableX = 0;
		this.lableY = 0;
		this.width = 0;
		this.lableWidth = 0;
		this.height = 0;
		this.page= 0;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public boolean isRequire() {
		return require;
	}

	public void setRequire(boolean require) {
		this.require = require;
	}
	
	public List<Map> getRadioButtonDate() {
		Gson gson = new Gson(); 
		List<Map> retList = gson.fromJson(this.dict,  
                new TypeToken<List<Map>>() {  
                }.getType());
		//设置RadioButton坐标
		Map last = null;
		int radiowidth = remarks.length() * 12;
			
		for(Map radio:retList){
			String radioLable = (String)radio.get("label");
			
			if(last == null){
				radio.put("radioX", x);
				radio.put("radioY", y); 
			}else{
				radio.put("radioX", (Integer)last.get("radioX")+15*(((String)last.get("label")).length()+2));
				if((Integer)radio.get("radioX")+15*(radioLable.length()+2)>fullWith){
					//如果超出长度则换行
					radio.put("radioX", x);
					radio.put("radioY", y+20);
				}else{
					radio.put("radioY", last.get("radioY"));
				}
			} 
			last = radio;
		}
		return retList==null?new ArrayList<Map>():retList;
	}

	public boolean isEditable() {
		return editable;
	}

	public void setEditable(boolean editable) {
		this.editable = editable;
	}
	
    public String getHbmType() {
        if (JavaTypeResolver.isInteger(javaType)){
            return "int";
        } else if (JavaTypeResolver.isDouble(javaType)){
            return "double";
        } else if (JavaTypeResolver.isFloat(javaType)){
            return "float";
        } else if (JavaTypeResolver.isLong(javaType)){
            return "long";
        } else if (JavaTypeResolver.isShort(javaType)){
            return "short";
        } else if (JavaTypeResolver.isBoolean(javaType)){
            return "boolean";
        } else if (JavaTypeResolver.isByte(javaType)){
            return "byte";
        }else if (JavaTypeResolver.isString(javaType)){
            return "string";
        }else if (JavaTypeResolver.isDate(javaType)){
            return "timestamp";
        } else {
            return javaType;
        }
    }
    
    public String getFlexType() {
        if (JavaTypeResolver.isInteger(javaType)){
            return "int";
        } else if (JavaTypeResolver.isDouble(javaType)){
            return "Number";
        } else if (JavaTypeResolver.isFloat(javaType)){
            return "Number";
        } else if (JavaTypeResolver.isLong(javaType)){
            return "int";
        } else if (JavaTypeResolver.isShort(javaType)){
            return "int";
        } else if (JavaTypeResolver.isBoolean(javaType)){
            return "Boolean";
        } else if (JavaTypeResolver.isByte(javaType)){
            return "String";
        }else if (JavaTypeResolver.isString(javaType)){
            return "String";
        }else if (JavaTypeResolver.isDate(javaType)){
            return "Date";
        } else {
            return javaType;
        }
    }
    
	public void setDefaultWidth(Column last) {
		if(this.ui.equals("CheckBox")){
			this.width = this.remarks.length() * 12;
		}
		else{	
			this.width = 125;
		}
	}
	
	public void getRadioButtonRemark() {
		
	}

	public String getGroupNo() {
		return groupNo;
	}

	public void setGroupNo(String groupNo) {
		this.groupNo = groupNo;
	}
	
	





}
